package com.wyz.note.basics.singleton.idler;

/**
 * @author wei yz
 * @ClassName: Singleton
 * @Description: 单例模式 - 懒汉式
 * @date 2023/4/8 14:23
 */
// 基础实现：线程不安全
public class Singleton {
    // 1. 类加载时，先不自动创建单例
    // 即，将单例的引用先赋值为 Null
    private static  Singleton ourInstance  = null;
    // 2. 构造函数 设置为 私有权限
    // 原因：禁止他人创建实例
    private Singleton() {
    }

    // 3. 需要时才手动调用 newInstance（） 创建 单例
    public static  Singleton newInstance() {
        // 先判断单例是否为空，以避免重复创建
        if( ourInstance == null){
            ourInstance = new Singleton();
        }
        return ourInstance;
    }
}

//--------------------------------------------------------------------
// 同步锁（懒汉式的改进）
// 写法1
class Singleton1 {
    // 1. 类加载时，先不自动创建单例
    //  即，将单例的引用先赋值为 Null
    private static  Singleton1 ourInstance  = null;

    // 2. 构造函数 设置为 私有权限
    // 原因：禁止他人创建实例
    private Singleton1() {
    }

    // 3. 加入同步锁
    public static synchronized Singleton1 getInstance(){
        // 先判断单例是否为空，以避免重复创建
        if ( ourInstance == null )
            ourInstance = new Singleton1();
        return ourInstance;
    }
}

// 写法2
// 该写法的作用与上述写法作用相同，只是写法有所区别
class Singleton2{
    private static Singleton2 instance = null;
    private Singleton2(){
    }
    public static Singleton2 getInstance(){
        // 加入同步锁
        synchronized(Singleton2.class) {
            if (instance == null)
                instance = new Singleton2();
        }
        return instance;
    }
}

//--------------------------------------------------------------------
// 双重校验锁（懒汉式的改进）
class Singleton3 {
    private static  Singleton3 ourInstance  = null;
    private Singleton3() {
    }

    public static  Singleton3 newInstance() {
        // 加入双重校验锁
        // 校验锁1：第1个if
        if( ourInstance == null){  // ①
            synchronized (Singleton3.class){ // ②
                // 校验锁2：第2个 if
                if( ourInstance == null){
                    ourInstance = new Singleton3();
                }
            }
        }
        return ourInstance;
    }
}
// 说明
// 校验锁1：第1个if
// 作用：若单例已创建，则直接返回已创建的单例，无需再执行加锁操作
// 即直接跳到执行 return ourInstance
// 校验锁2：第2个 if
// 作用：防止多次创建单例问题
// 原理
// 1. 线程A调用newInstance()，当运行到②位置时，此时线程B也调用了newInstance()
// 2. 因线程A并没有执行instance = new Singleton();，此时instance仍为空，因此线程B能突破第1层 if 判断，运行到①位置等待synchronized中的A线程执行完毕
// 3. 当线程A释放同步锁时，单例已创建，即instance已非空
// 4. 此时线程B 从①开始执行到位置②。此时第2层 if 判断 = 为空（单例已创建），因此也不会创建多余的实例